#!/usr/bin/env python3
# encoding: utf-8

"""
@version: 1.0
@author: 周永波
@file: serialization.py
@time: 2020/8/18 17:08
"""
import _json
import uuid
from datetime import date, datetime
from typing import Tuple

from flask._compat import text_type
from flask.json import JSONEncoder as _JSONEncoder, dataclasses
from flask import Flask as _Flask, json

# 自定义json 序列化器
from werkzeug.http import http_date

commonFields = ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
                '__getattribute__',
                '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__mapper__', '__module__',
                '__ne__',
                '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
                '__subclasshook__',
                '__table__', '__tablename__', '__weakref__', '_decl_class_registry', '_sa_class_manager',
                '_sa_instance_state',
                'metadata', 'query', 'query_class']


class JSONEncoder(_JSONEncoder):

    def default(self, o):
        if isinstance(o, datetime):
            return http_date(o.utctimetuple())
        if isinstance(o, date):
            return http_date(o.timetuple())
        if isinstance(o, uuid.UUID):
            return str(o)
        if dataclasses and dataclasses.is_dataclass(o):
            return dataclasses.asdict(o)
        if hasattr(o, "__html__"):
            return text_type(o.__html__())
        if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
            return dict(o)
        return self.property_con(o)

    def property_con(self, o):
        psFields = dir(o)
        cjFields = list(set(psFields) ^ set(commonFields))
        dict_obj = {}
        for field in cjFields:
            val = getattr(o, field)
            if dataclasses and dataclasses.is_dataclass(val):
                val = val.__dict__
            elif isinstance(val, (Tuple, list, set)):
                val = json.loads(json.dumps(val))
            # if(val is not None and isinstance(val,Object)):
            dict_obj.update({field: val})
        return dict_obj
